import { useEffect, useRef, useState } from "react";
import "./style.less";
import { Button, message as amessage } from "antd";
import { useLocation } from "react-router-dom";
import { CopyOutlined } from "@ant-design/icons";
import copy from "copy-to-clipboard";

const Video = () => {
  const location = useLocation();
  const target = location.search.slice(6);
  const loggerRef = useRef<HTMLDivElement>(null);
  const localVideoRef = useRef<HTMLVideoElement>(null);
  const remoteVideoRef = useRef<HTMLVideoElement>(null);
  const [isStarted, setIsStarted] = useState(false);
  const [visible, setVisible] = useState(true);

  const message = {
    el: loggerRef,
    log(msg: string) {
      this.el.current.innerHTML += `<span>${new Date().toLocaleTimeString()}：${msg}</span><br/>`;
    },
    error(msg: string) {
      this.el.current.innerHTML += `<span class="error">${new Date().toLocaleTimeString()}：${msg}</span><br/>`;
    },
  };

  const PeerConnection =
    window.RTCPeerConnection ||
    window.mozRTCPeerConnection ||
    window.webkitRTCPeerConnection;
  const peer = new PeerConnection();

  const socket = new WebSocket("ws://localhost:3001");

  useEffect(() => {
    localVideoRef.current.onloadeddata = () => {
      message.log("播放本地视频");
      localVideoRef.current.play();
    };
    remoteVideoRef.current.onloadeddata = () => {
      message.log("播放对方视频");
      remoteVideoRef.current.play();
    };

    document.title = target === "offer" ? "发起方" : "接收方";

    message.log("信令通道（WebSocket）创建中......");
  }, []);

  const hangUp = async () => {
    try {
      // 向 WebSocket 发送 hangUp 消息
      socket.send(
        JSON.stringify({
          type: "hangUp",
        })
      );
      // setIsStarted(false);
      window.location.reload();
    } catch (error) {
      console.error(error);
    }
  };

  useEffect(() => {
    if (!PeerConnection) {
      message.error("浏览器不支持WebRTC！");
      return;
    }

    peer.ontrack = (e) => {
      if (!e.streams || !e.streams.length) {
        message.error("没有收到对方音频/视频流数据！");
        return;
      }
      message.log("收到对方音频/视频流数据...");
      remoteVideoRef.current.srcObject = e.streams[0];
    };

    peer.onicecandidate = (e) => {
      if (!e.candidate) {
        message.log("候选人收集完成！");
        socket.send(
          JSON.stringify({
            type: `${target}_ice`,
            iceCandidate: null,
          })
        );
        return;
      }
      message.log("搜集并发送候选人");
      socket.send(
        JSON.stringify({
          type: `${target}_ice`,
          iceCandidate: e.candidate,
        })
      );
    };

    socket.onopen = () => {
      message.log("信令通道创建成功！");
    };

    socket.onerror = () => {
      message.error("信令通道创建失败！");
    };

    socket.onmessage = (e) => {
      try {
        const { type, sdp, iceCandidate } = JSON.parse(e.data);
        if (type === "answer") {
          peer.setRemoteDescription(new RTCSessionDescription({ type, sdp }));
        } else if (type === "answer_ice") {
          peer.addIceCandidate(iceCandidate);
        } else if (type === "offer") {
          startLive(new RTCSessionDescription({ type, sdp }));
        } else if (type === "offer_ice") {
          peer.addIceCandidate(iceCandidate);
        } else if (type === "hangUp") {
          // setIsStarted(false);
          window.location.reload();
        } else {
          message.error(`收到了未知类型的消息：${type}`);
        }
      } catch (err) {
        message.error(`收到了无法解析的消息：${e.data}`);
      }
    };
  }, []);

  async function startLive(offerSdp?: RTCSessionDescription) {
    let stream: MediaStream;
    try {
      message.log("尝试调取本地摄像头/麦克风");
      stream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true,
      });
      message.log("摄像头/麦克风获取成功！");
      localVideoRef.current.srcObject = stream;
    } catch (err) {
      message.error("摄像头/麦克风获取失败！");
      return;
    }

    message.log(
      `------ WebRTC ${target === "offer" ? "发起方" : "接收方"}流程开始 ------`
    );
    message.log("将媒体轨道添加到轨道集");
    stream.getTracks().forEach((track) => {
      peer.addTrack(track, stream);
    });

    if (!offerSdp) {
      message.log("创建本地SDP");
      const offer = await peer.createOffer();
      await peer.setLocalDescription(offer);
      message.log(`传输发起方本地SDP`);
      socket.send(JSON.stringify(offer));
    } else {
      message.log("接收到发送方SDP");
      await peer.setRemoteDescription(offerSdp);

      message.log("创建接收方（应答）SDP");
      const answer = await peer.createAnswer();
      message.log(`传输接收方（应答）SDP`);
      socket.send(JSON.stringify(answer));
      await peer.setLocalDescription(answer);
    }
    setIsStarted(true);
  }

  const handleCopy = () => {
    copy('http://localhost:5173/video?type=answer');
    amessage.success("会议号已复制到剪贴板");
  }

  return (
    <div className="container">
      <div className="video-box" style={{ width: visible ? "92vw" : "800px" }}>
      {target === 'offer' && <>{'会议号：' + location.state.id}<CopyOutlined onClick={handleCopy} /></> }
        <div style={{ position: "relative", color: "#fff" }}>
          <video id="remote-video" ref={remoteVideoRef}></video>
          <span
            style={{
              position: "absolute",
              zIndex: 100,
              bottom: 0,
              left: 0,
              borderRadius: "5px",
              backgroundColor: "rgba(0, 0, 0, 0.1)",
            }}
          >
            {target === "offer" ? "面试官（我）" : "候选人（我）"}
          </span>
        </div>
        <div style={{ position: "relative", color: "#fff" }}>
          <video id="local-video" muted ref={localVideoRef}></video>
          <span
            style={{
              position: "absolute",
              bottom: 0,
              right: 0,
              borderRadius: "5px",
              backgroundColor: "rgba(0, 0, 0, 0.1)",
            }}
          >
            {target === "offer" ? "候选人" : "面试官"}
          </span>
        </div>
        {isStarted ? (
          <Button type="primary" onClick={hangUp}>
            挂断
          </Button>
        ) : (
          <>
            {target == "offer" ? (
              <Button
                type="primary"
                style={{ position: "absolute", top: "70%", left: "50%" }}
                onClick={() => startLive()}
              >
                start
              </Button>
            ) : null}
            {target == "answer" && !isStarted ? (
              <span style={{ position: "absolute", top: "70%", left: "45%" }}>
                面试官未加入面试间,请等待...
              </span>
            ) : null}
          </>
        )}
      </div>
      {isStarted && <Button
        style={{ position: "absolute", top: 0, right: 0 }}
        onClick={() => setVisible(!visible)}
      >
        {visible ? "打开日志" : "收起日志"}
      </Button>}
      <div
        className="logger"
        style={{
          position: "absolute",
          width: visible ? 0 : "40%",
          padding: visible ? 0 : "14px",
          top: "40px",
          right: 0,
        }}
        ref={loggerRef}
      ></div>
    </div>
  );
};

export default Video;
